﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Xml.XPath;
using System.Diagnostics;
using System.IO;

namespace RESTester
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window, INotifyPropertyChanged
    {
        #region Content Types

        public List<string> _contentTypes = new List<string>
                                                {
                                                    "text/css",
                                                    "text/csv",
                                                    "text/html",
                                                    "text/javascript",
                                                    "text/plain",
                                                    "text/xml",
                                                    "video/mpeg",
                                                    "video/mp4",
                                                    "video/ogg",
                                                    "video/quicktime",
                                                    "video/x-ms-wmv",
                                                    "application/x-pkcs12",
                                                    "application/x-pkcs12",
                                                    "application/x-pkcs7-certificates",
                                                    "application/x-pkcs7-certificates",
                                                    "application/x-pkcs7-certreqresp",
                                                    "application/x-pkcs7-mime",
                                                    "application/x-pkcs7-mime",
                                                    "application/x-pkcs7-signature",
                                                    "multipart/mixed",
                                                    "multipart/alternative",
                                                    "multipart/related",
                                                    "multipart/form-data",
                                                    "multipart/signed",
                                                    "multipart/encrypted",
                                                    "application/x-www-form-urlencoded",
                                                    "application/EDI-X12",
                                                    "application/EDIFACT",
                                                    "application/javascript",
                                                    "application/octet-stream",
                                                    "application/ogg",
                                                    "application/pdf",
                                                    "application/xhtml+xml",
                                                    "application/xml-dtd",
                                                    "application/json",
                                                    "application/zip",
                                                    "image/gif",
                                                    "image/jpeg",
                                                    "image/png",
                                                    "image/svg+xml",
                                                    "image/tiff",
                                                    "image/vnd.microsoft.icon",
                                                    "application/vnd.oasis.opendocument.text",
                                                    "application/vnd.oasis.opendocument.spreadsheet",
                                                    "application/vnd.oasis.opendocument.presentation",
                                                    "application/vnd.oasis.opendocument.graphics",
                                                    "application/vnd.ms-excel",
                                                    "application/vnd.ms-powerpoint",
                                                    "application/msword",
                                                    "application/vnd.mozilla.xul+xml",
                                                    "audio/basic",
                                                    "audio/mpeg",
                                                    "audio/ogg",
                                                    "audio/vorbis",
                                                    "audio/x-ms-wma",
                                                    "audio/vnd.rn-realaudio",
                                                    "audio/x-wav"
                                                };

        public List<String> ContentTypes { get { return _contentTypes; } }

        #endregion

        #region INotifyPropertyChanged

        public event PropertyChangedEventHandler PropertyChanged;

        private void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        #endregion

        private List<HTTPHeader> _requestHeaders;
        public List<HTTPHeader> RequestHeaders
        {
            get
            {
                return _requestHeaders;
            }
            set
            {
                _requestHeaders = value;
                OnPropertyChanged("RequestHeaders");
            }
        }


        private List<HTTPHeader> _responseHeaders;
        public List<HTTPHeader> ResponseHeaders
        {
            get
            {
                return _responseHeaders;
            }
            set
            {
                _responseHeaders = value;
                OnPropertyChanged("ResponseHeaders");
            }
        }

        private List<Request> _requests;
        public List<Request> Requests
        {
            get
            {
                return _requests;
            }
            set
            {
                _requests = value;
                OnPropertyChanged("Requests");
            }
        }

        private int _currentRequestId;
        private const string _layoutFileName = "last.layout";

        public MainWindow()
        {
            InitializeComponent();

            loader.Image = RESTester.Properties.Resources.loader;

            #region 4test
#if DEBUG
            requestUrl.Text = "http://www.site.local/";
            contentTypeBox.SelectedIndex = 25;
#endif
            #endregion

            RequestHeaders = new List<HTTPHeader>();
            ResponseHeaders = new List<HTTPHeader>();

            Loaded += (s, e) => {  DataContext = this; };

            dockManager.Loaded += (s, e) =>
            {
                if (File.Exists(_layoutFileName))
                {
                    dockManager.RestoreLayout(_layoutFileName);
                }
            };

            Closing += (s, e) =>
                {
                        dockManager.SaveLayout(_layoutFileName);
                };

            RESTesterLogic.Instance.RequestStart += (List<HTTPHeader> headers) =>
                                                  {
                                                      requestContentTextBox.Dispatcher.Invoke((Action)(() => requestContentTextBox.IsReadOnly = true));
                                                      RequestHeaders = headers;
                                                      WriteLog("Request is started ...");
                                                      loaderBlock.Dispatcher.Invoke((Action)(() => loaderBlock.Visibility = System.Windows.Visibility.Visible));
                                                  };

            RESTesterLogic.Instance.RequestEnd += (string plainText, string xml, string json, List<HTTPHeader> headers) =>
                                                  {
                                                      requestContentTextBox.Dispatcher.Invoke((Action)(() => requestContentTextBox.IsReadOnly = false));
                                                      responseTextBox.Dispatcher.Invoke((Action)(() => responseTextBox.Text = plainText));
                                                      responseXmlTextBox.Dispatcher.Invoke((Action)(() => responseXmlTextBox.Text = xml));
                                                      responseJsonTextBox.Dispatcher.Invoke((Action)(() => responseJsonTextBox.Text = json));
                                                      responseWebBrowser.Dispatcher.Invoke((Action)(() => responseWebBrowser.NavigateToString(plainText)));

                                                      ResponseHeaders = headers;

                                                      WriteLog("Request is ended ...");
                                                      loaderBlock.Dispatcher.Invoke((Action)(() => loaderBlock.Visibility = System.Windows.Visibility.Hidden));
                                                  };

            RESTesterLogic.Instance.Log += (string message) =>
                                                  {
                                                      WriteLog(message);
                                                  };

            LoadRequests();
        }

        private void WriteLog(string message)
        {
            logTextBox.Dispatcher.Invoke((Action)(() => logTextBox.Text += string.Format("{0} >>{1}{2}", DateTime.Now.ToString(), message, Environment.NewLine)));
            logTextBox.Dispatcher.Invoke((Action)(() => logTextBox.ScrollToEnd()));
        }

        private void getBtn_Click(object sender, RoutedEventArgs e)
        {
            RESTesterLogic.Instance.DoRequest(
                                    requestUrl.Text,
                                    (HTTPMethod)methodBox.SelectedItem,
                                    RequestHeaders,
                                    (string)contentTypeBox.SelectedItem,
                                    requestContentTextBox.Text);
        }

        private void loadRequests_Click(object sender, RoutedEventArgs e)
        {
            LoadRequests();
        }

        private void saveRequest_Click(object sender, RoutedEventArgs e)
        {
            Request request = new Request(
                                    requestUrl.Text,
                                    (HTTPMethod)methodBox.SelectedItem,
                                    requestContentTextBox.Text,
                                    RequestHeaders,
                                    (string)contentTypeBox.SelectedItem,
                                    requestNameTextBox.Text);
            request.Id = _currentRequestId;
            if (RESTesterLogic.Instance.SaveToDb(request))
            {
                requestNameTextBox.Clear();
                LoadRequests();
            }
        }

        private void LoadRequests()
        {
            List<Request> requests;
            if (RESTesterLogic.Instance.LoadFromDb(out requests))
            {
                Requests = requests;
            }
        }

        private void clearAll_Click(object sender, RoutedEventArgs e)
        {
            requestUrl.Clear();
            methodBox.SelectedItem = HTTPMethod.GET;
            requestContentTextBox.Clear();
            requestHeadersGrid.ItemsSource = null;
        }

        private void Do()
        {
            string fileName = @"C:\Users\Jorgen\Downloads\Kushal's Java Blog   Software Engineering Blog » Blog » List of All Available Major MIME Types.htm";
            XPathDocument doc = new XPathDocument(fileName);
            XPathNavigator nav = doc.CreateNavigator();

            // Compile a standard XPath expression
            XPathExpression expr;
            expr = nav.Compile("/tbody/tr/td[3]/text()");
            XPathNodeIterator iterator = nav.Select(expr);

            StringBuilder builder = new StringBuilder();

            while (iterator.MoveNext())
            {
                XPathNavigator nav2 = iterator.Current.Clone();
                builder.AppendFormat("\"{0}\",\n", nav2.Value);
            }

            var v = builder.ToString();
        }

        private void loadMenuItem_Click(object sender, RoutedEventArgs e)
        {
            Request request;
            if (TryGetRequestFromMenuItem(e, out request))
            {
                requestUrl.Text = request.Url;
                methodBox.SelectedItem = request.Method;
                requestContentTextBox.Text = request.Data;
                requestHeadersGrid.ItemsSource = request.Headers;
                contentTypeBox.SelectedItem = request.ContentType;
                requestNameTextBox.Text = request.Name;
                _currentRequestId = request.Id;
            }
        }

        private void removeMenuItem_Click(object sender, RoutedEventArgs e)
        {
            Request request;
            if (TryGetRequestFromMenuItem(e, out request))
            {
                if (RESTesterLogic.Instance.RemoveFromDB(request))
                {
                    LoadRequests();
                }
            }
        }

        private bool TryGetRequestFromMenuItem(RoutedEventArgs args, out Request request)
        {
            bool result = false;
            request = null;
            MenuItem menuItem = args.Source as MenuItem;
            if (menuItem != null)
            {
                request = menuItem.DataContext as Request;
                if (request != null)
                {
                    result = true;
                }
            }

            return result;
        }

        private void donateBtn_Click(object sender, RoutedEventArgs e)
        {
            Process.Start("http://donate.smscoin.com/js/smsdonate/index_en.html?sid=101038&language=english");
        }

        private void requestNameTextBox_KeyDown(object sender, System.Windows.Input.KeyEventArgs e)
        {
            if (e.Key == System.Windows.Input.Key.Enter)
            {
                saveRequest_Click(null, null);
            }
        }
    }
}
